/**
 * 本文主要讨论Deref特质
 * 1.所谓的Deref特质，并不是是说解除引用的意思，而是把指针中的值通过应用的方式进行输出。
 * 名称取得并不好，大概rust的发明人文学水平较为糟糕。我个人更加愿意把 Deref理解为 Deliver reference
 * 
 * 2.即使是简单的Box指针，那么在为指针赋值的时候，实际是夺取了指针指向的值的所有权，所以不存在转移权限的问题。
 *   如果原值是栈类型，则是例外，因为是直接复制，所以不存在转移权限的问题。
 *   这种夺权的行为，和其它类型赋值是类似的，例如把String作为struct的一部分；又例如例如把String作为enum的一部分。
 *   ;把String作为Vec的一个部分
 * 3.使用*获取Box的值，实质是返回所有权（或者克隆后的值），不是引用。  熟练它的实现是令人迷惑的 &xxx
 *   相关文档上的描述也是不准确的。 所以应该看效果，而不是看文字描述
 *   *Box 实际执行的是 *(Deref Box<T>)  ,由于Deref返回的引用类型，再通过*处理，则返回的是T类型，具有所有权
 * 
 */
use std::ops::Deref;

struct MyBox<T>(T);

impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> {
        MyBox(x)
    }
}

impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        //从返回类型可以看出，所谓的Deref,其实是提供引用
        &self.0
    }
}
#[derive(Debug)]
struct Family{
    father:String,
    mother:String,
    son:String,
    daughter:String
}

fn main() {
    let x = 5;

    //测试自定义的智能指针
    let y = MyBox::new(x);   //x是一个栈变量，这里是克隆，所以不存在转移权限的问题。
    let y1=*y;
    if x==y1 { 
        println!("y={}", x);
    }
    println!("x={}", x);
    let y2=*y;

    //默认的Box智能指针，已经实现了Deref，所以可以直接解引用
    let z = Box::new(5);
    if x==*z { 
        println!("z={}", x);
    }

    let cn=String::from("中国");
    let cn_box=Box::new(cn);
    println!("length of {} is {}",cn_box,cn_box.len());
    let pcn=*cn_box;
    println!("length of {} is {}",pcn,pcn.len());
    //let pcn2=*cn_box;   这里会报错，因为 *Box 返回的是Box值的所有权，而不是引用。 value used here after move
    //println!("length of {} is {}",pcn2,pcn2.len()); 


    let family=Family{
        father:String::from("父亲"),
        mother:String::from("母亲"),
        son:String::from("儿子"),
        daughter:String::from("女儿")
    };
    let  mybox1=MyBox::new(family);

    println!("{:?}",*mybox1);


}

